#ifndef __NETTHUMB_H__
#define __NETTHUMB_H__

#include <map>
#include <vector>
#include <string>

// Identificadores para los atributos de DeviceI
#define DEVICE_ADDRID 10
//#define DEVICE_DEVADDR 1
#define DEVICE_NETID  12
#define DEVICE_LINKST 13
#define DEVICE_NETSCOPE 14
#define DEVICE_ID 15
#define DEVICE_LINKID 16
#define DEVICE_LOCATION 17

// Identificadores para los atributos de ConfRouteI
#define CONFROUTE_NETTYPE 20
#define CONFROUTE_NETID 21
#define CONFROUTE_DEVICEID 22
#define CONFROUTE_VIAADDR 23
#define CONFROUTE_METRIC 24
#define CONFROUTE_MORP 25
#define CONFROUTE_LOCATION 26

// Identificadores para los atributos de RouteI
#define ROUTE_DEVICEID 30
#define ROUTE_VIAADDR  31
#define ROUTE_METRIC   32
#define ROUTE_MORP 33
#define ROUTE_LOCATION 34

// Identificadores para los atributos de HostI
#define HOST_ID 40
#define HOST_LOCATION 41

// Identificadores para los atributos de RouterI
#define ROUTER_ID 50
#define ROUTER_LOCATION 51

// Identificadores para los atributos de NetworkI
#define NETWORK_ID 60
#define NETWORK_ADDRID 61
#define NETWORK_TYPEID 62
#define NETWORK_MULTICAST 63
#define NETWORK_MTU 64
#define NETWORK_LOCATION 65
 
using namespace std;

namespace netthumb {

  enum NetScope {nullScope, global, site, link, host};
  enum NetType {nullType, unicast, unreachable, blackhole,
		prohibit, local, broadcast,
		thrown, nat, anycast, multicast};
  enum LinkSt {nullSt, up, down};

  // Subtipo DeviceI, de la clase HostI
  class DeviceI {

  private:
    LinkSt _linkSt;
    string _addressID;
    string _networkID;
    string _linkID;
    NetScope _scope;
    string _location;

  public:

    DeviceI();

    void populate(string addressID,
		  string networkID,
		  string linkID,
		  string location);

    void setLinkSt(LinkSt link);
    void setScope(NetScope scope);

    string getAddressID();
    string getNetID();
    string getLinkID();
    string getLocation();
    LinkSt getLinkSt();
    NetScope getScope();
    string toString();
  };

  // Subtipo de RouteI, perteneciente a la clase HostI
  class ConfRouteI {
  private:
    NetType _netType;
    string _netID;
    string _deviceID;
    string _viaAddr;
    bool _metric; // true := metric; false := priority
    int _metricVal;
    string _location;

  public:
    ConfRouteI();

    void populate(string netID,
		  string deviceID,
		  string location);
    void setViaAddr(string viaAddr);
    void setNetType(NetType netType);
    void setMetric(int metric);
    void setMetricOrPriority(bool metric);

    bool getMetricOrPriority();
    string getNetID();
    string getDeviceID();
    string getViaAddr();
    string getLocation();
    NetType getNetType();
    int getMetric();
    string toString();
  };

  // Subtipo RouteI, perteneciente a HostI
  class RouteI {

  private:
    vector<ConfRouteI*> _configurations;
    string _deviceID;
    string _viaAddr;
    bool _metric; // true := metric; false := priority
    int _metricVal;
    string _location;

  public:
    RouteI();

    void setLocation(string location);
    void insertConf(ConfRouteI* conf);
    void setDeviceID(string deviceID);
    void setViaAddr(string viaAddr);
    void setMetric(int metricVal);
    void setMetricOrPriority(bool metric);

    string getDeviceID();
    string getViaAddr();
    string getLocation();
    bool getMetricOrPriority();
    int getMetric();
    vector<ConfRouteI*>& getConfigurations();
    string toString();
  };


  // HostI
  class HostI {

  private:
    RouteI* _route;
    map<string, DeviceI*> _devMap;
    string _location;

  public:
    HostI();
    void insertDevice(string name, DeviceI* device);
    void setDevices(map<string, DeviceI*>& devices);
    void setRoute(RouteI* route);
    void setLocation(string location);
    
    RouteI* getRoute();
    map<string, DeviceI*>& getDevices();
    string getLocation();
    string toString();
  };

  // RouterI
  class RouterI {

  private:
    RouteI* _route;
    map<string, DeviceI*> _devMap;
    string _location;

  public:
    RouterI();

    void insertDevice(string name, DeviceI* device);
    void setDevices(map<string, DeviceI*>& devices);
    void setRoute(RouteI* route);
    void setLocation(string location);

    map<string, DeviceI*>& getDevices();
    RouteI* getRoute();
    string getLocation();
    string toString();
  };

  // NetworkI
  class NetworkI {

  private:
    string _addressID;
    int _mtu;
    bool _multicast;
    string _typeID;
    string _location;

  public:
    NetworkI();
    void populate(string addressID,
		  string typeID,
		  int mtu,
		  bool multicast,
		  string location);

    string getAddress();
    string getTypeID();
    bool isMulticast();
    int getMtu();
    string getLocation();
    string toString();
  };
}

#endif
